home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et-2_2.lha / et2.2 / src / SUNOS / dynlink.c next >
C/C++ Source or Header  |  1990-11-29  |  19KB  |  876 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3.  
  4. typedef void* ((*func_ptr)());
  5.  
  6. static void *func_error()
  7. {
  8.     fprintf(stderr, "func_error in DynCall\n");
  9.     return 0;
  10. }
  11.  
  12. #ifdef sun
  13.  
  14. #if defined(sun4) || defined(sparc)
  15. #       include <sun4/a.out.h>
  16. #       undef relocation_info
  17. #       define relocation_info reloc_info_sparc
  18. #       define r_symbolnum r_index
  19. #       define MASK(n) ((1<<(n))-1)
  20. #       define M(a,d,n) *(long*)(a)= (*(long*)(a) & ~MASK(n)) | ((d) & MASK(n))
  21. #else
  22. #       include <a.out.h>
  23. #       undef relocation_info
  24. #       define relocation_info reloc_info_68k
  25. #endif /* sun4 */
  26.  
  27. #include <sys/file.h>
  28. #include <sys/types.h>
  29. #include <errno.h>
  30. #include <sys/param.h>
  31. #include <sys/stat.h>
  32.  
  33. #define bad_format 2
  34. #define ok 0
  35.  
  36. /* The hash value is a function of the table size. */
  37. #define hash(h,ss,m) { register char *_s=ss; for(h=0; *_s;) h+=((h<<1)+*_s++); h&=m; }
  38.  
  39. #define REHASH(hash, table) (((hash+1)*3) & (table)->mask)
  40.  
  41. #define INIT_TABLE_SIZE 8192    /* Must be a power of two */
  42.  
  43.  
  44. typedef struct {
  45.     struct nlist **array; 
  46.     int size;           /* Number of slots in table.. power of 2 */
  47.     int mask;           /* always = size-1, for calculating (num mod size)*/
  48.     int entries;        /* number of entries in AssocTable */
  49. } AssocTable;
  50.  
  51. struct Module {
  52.     char *name, *name1;
  53.     int fd;
  54.     struct Module *next;
  55.     struct nlist *symtab, *endp;
  56.     long text;
  57.     func_ptr dtor;
  58.     int undefs;
  59.     struct exec header;
  60. };
  61.  
  62. extern char *malloc(), *calloc(), *strcpy(), *getenv();
  63.  
  64. static AssocTable *mainhashtable= 0;
  65. static struct Module mainmodule;
  66. static struct Module *firstModule= 0;
  67. static long new_common= 0;
  68. static char *etdir;
  69. static char *STD, *STI;
  70. static int STDlen, STIlen;
  71. static int ccversion= 1;
  72.  
  73. static char *strsave(s)
  74. char *s;
  75. {
  76.     return strcpy(malloc(strlen(s)+1), s);
  77. }
  78.  
  79. static struct Module *FindModule(name)
  80. char *name;
  81. {
  82.     register struct Module *mp;
  83.     
  84.     for (mp= firstModule; mp; mp= mp->next)
  85.     if (strcmp(name, mp->name) == 0)
  86.         return mp;
  87.     return 0;
  88. }
  89.  
  90. static struct Module *AddModule(name, name1)
  91. char *name, *name1;
  92. {
  93.     struct Module *mp;
  94.     
  95.     mp= (struct Module *) calloc(1, sizeof(struct Module));
  96.     mp->next= firstModule;
  97.     mp->undefs= 0;
  98.     mp->fd= -1;
  99.     mp->name= strsave(name);
  100.     mp->name1= strsave(name1);
  101.     mp->dtor= 0;
  102.     
  103.     return firstModule= mp;
  104. }
  105.  
  106. static AssocTable *NewAssocTable()
  107. {
  108.     register AssocTable* table;
  109.  
  110.     table= (AssocTable*) calloc(1, sizeof(AssocTable));
  111.  
  112.     table->size= INIT_TABLE_SIZE;
  113.     table->mask= table->size-1;
  114.     table->array= (struct nlist**) calloc(table->size, sizeof(struct nlist*));
  115.  
  116.     return table;
  117. }
  118.  
  119. static void ExpandTable(table)
  120. register AssocTable* table;
  121. {
  122.     register struct nlist **old_table, **sym, **endp, *sp;
  123.     register int rehash;
  124.     int old_size;
  125.  
  126.     old_table= table->array;
  127.     old_size= table->size;
  128.     table->size*= 2;
  129.     table->mask= table->size-1;
  130.     table->array= (struct nlist**) calloc(table->size, sizeof(struct nlist*));
  131.  
  132.     /* Move the members from the old small table to the new big one. */
  133.     sym= old_table;
  134.     endp= sym + old_size;
  135.     for (; sym < endp; sym++) {
  136.     if (sp= *sym) {
  137.         hash(rehash, sp->n_un.n_name, table->mask);
  138.         while (table->array[rehash])
  139.         rehash= REHASH(rehash, table);
  140.         table->array[rehash]= sp;
  141.     }
  142.     }
  143.     free(old_table);
  144. }
  145.  
  146. static void Assoc(table, sym)
  147. register AssocTable* table;
  148. struct nlist *sym;
  149. {
  150.     register int rehash;
  151.     struct nlist *s;
  152.  
  153.     if (table->entries >= (table->size/2) - 1)
  154.     ExpandTable(table);
  155.  
  156.     hash(rehash, sym->n_un.n_name, table->mask);
  157.     while (s= table->array[rehash]) {
  158.     if (strcmp(s->n_un.n_name, sym->n_un.n_name) == 0)
  159.         return;
  160.     rehash= REHASH(rehash, table);
  161.     }
  162.     table->array[rehash]= sym;
  163.     table->entries++;
  164. }
  165.  
  166. static struct nlist *Lookup(table, name)
  167. register AssocTable* table;
  168. char *name;
  169. {
  170.     register struct nlist *syms;
  171.     register int rehash;
  172.  
  173.     hash(rehash, name, table->mask);
  174.     while (syms= table->array[rehash]) {
  175.     if (strcmp(syms->n_un.n_name, name) == 0)
  176.         return syms;
  177.     rehash= REHASH(rehash, table);
  178.     }
  179.     return 0;
  180. }
  181.  
  182. static char *which(search, file)
  183. char *search, *file;
  184. {
  185.     static char name[MAXPATHLEN];
  186.     register char *ptr, *next;
  187.     struct stat buffer;
  188.  
  189.     if (file[0] == '/') {
  190.     if (stat(file, &buffer) != -1)
  191.         return file;
  192.     return 0;
  193.     }
  194.  
  195.     if (search == 0)
  196.     search= ".";
  197.  
  198.     for (ptr= search; *ptr;) {
  199.     for (next= name; *ptr && *ptr != ':'; )
  200.         *next++= *ptr++;
  201.     *next= '\0';
  202.        
  203.     strcat(name, "/");
  204.     strcat(name, file);
  205.        
  206.     if (stat(name, &buffer) != -1)
  207.         return name;
  208.     if (*ptr)
  209.         ptr++;
  210.     }
  211.     return 0;
  212. }
  213.  
  214. static void GetHeader(mp)
  215. struct Module *mp;
  216. {
  217.     lseek(mp->fd, 0, L_SET);
  218.     if (read(mp->fd, &mp->header, sizeof(struct exec)) != sizeof(struct exec)) {
  219.     perror("GetHeader: read error");
  220.     _exit(1);
  221.     }
  222. }
  223.  
  224. static void GetSymbols(mp)
  225. struct Module *mp;
  226. {
  227.     register struct nlist *buffer, *sym;
  228.     unsigned long size;
  229.     long displ;
  230.  
  231.     lseek(mp->fd, N_SYMOFF(mp->header) + mp->header.a_syms, L_SET);
  232.     if (read(mp->fd, &size, 4) != 4) {
  233.     perror("GetSymbols: read error");
  234.     _exit(1);
  235.     }
  236.  
  237.     buffer= (struct nlist*) calloc(1, mp->header.a_syms + size);
  238.   
  239.     lseek(mp->fd, N_SYMOFF(mp->header), L_SET);
  240.     if (read(mp->fd, buffer, mp->header.a_syms + size) != mp->header.a_syms + size) {
  241.     free(buffer);
  242.     perror("GetSymbols: read error");
  243.     _exit(1);
  244.     }
  245.   
  246.     mp->symtab= buffer;
  247.     mp->endp= buffer + (mp->header.a_syms/sizeof(struct nlist));
  248.     
  249.     displ= (long)buffer + (long)(mp->header.a_syms);
  250.  
  251.     for (sym= buffer; sym < mp->endp; sym++)
  252.     sym->n_un.n_name= (char*) sym->n_un.n_strx + displ;
  253. }
  254.  
  255. static struct relocation_info *GetRelocInfo(mp)
  256. struct Module *mp;
  257. {
  258.     struct relocation_info *buffer;
  259.     int size= mp->header.a_trsize + mp->header.a_drsize;
  260.   
  261.     if (size == 0) {
  262.     fprintf(stderr, "no relocation info\n");
  263.     return 0;
  264.     }
  265.     
  266.     buffer= (struct relocation_info*) calloc(1, size);
  267.  
  268.     lseek(mp->fd, N_TXTOFF(mp->header) + mp->header.a_text + mp->header.a_data, L_SET);
  269.   
  270.     if (read(mp->fd, buffer, size) != size) {
  271.     perror("GetRelocInfo: read");
  272.     free(buffer);
  273.     return 0;
  274.     }
  275.   
  276.     return buffer;
  277. }
  278.  
  279. static void GetTextAndData(mp)
  280. struct Module *mp;
  281. {
  282.     int size, rsize;
  283.     
  284.     lseek(mp->fd, N_TXTOFF(mp->header), L_SET);
  285.   
  286.     rsize= mp->header.a_text + mp->header.a_data;
  287.     size= rsize + mp->header.a_bss;
  288.  
  289.     mp->text= (long) malloc(size);
  290.   
  291.     if (read(mp->fd, mp->text, rsize) !=  rsize) {
  292.     perror("GetTextAndData: read error");
  293.     free(mp->text);
  294.     mp->text= 0;
  295.     return;
  296.     }
  297.     
  298.     bzero(mp->text + mp->header.a_text + mp->header.a_data, mp->header.a_bss);
  299. }
  300.  
  301. static void FindAll(mp, hashtable)
  302. struct Module *mp;
  303. AssocTable* hashtable;
  304. {
  305.     register struct nlist *symp= mp->symtab, *symbol;
  306.     int value;
  307.  
  308.     mp->undefs= 0;
  309.     for (; symp < mp->endp; symp++) {
  310.     if (symp->n_type & N_EXT) {
  311.         symbol= Lookup(hashtable, symp->n_un.n_name);
  312.  
  313.         if ((symp->n_type == N_EXT + N_UNDF) && (symbol == 0)) {
  314.         value= symp->n_value;
  315.         if (value > 0) {    /* is common */
  316.             int rnd= value >= sizeof(double) ? sizeof(double) - 1
  317.                    : value >= sizeof(long) ? sizeof(long) - 1
  318.                    : sizeof(short) - 1;
  319.  
  320.             symp->n_type= N_COMM;
  321.             new_common+= rnd;
  322.             new_common&= ~(long)rnd;
  323.             symp->n_value= new_common;
  324.             new_common+= value;
  325.             Assoc(hashtable, symp);
  326.         } else {
  327.             mp->undefs++;
  328.             try(symp->n_un.n_name);
  329.         }
  330.         } else if (symbol == 0) /* is new */
  331.         Assoc(hashtable, symp);
  332.     }
  333.     }
  334. }
  335.  
  336. static int Testload(name)
  337. char* name;
  338. {
  339.     char buf[100], buf2[100], *name2, *dynpath;
  340.     struct Module *mp;
  341.     
  342.     sprintf(buf, "%s.o", name);
  343.     
  344.     dynpath= getenv("ET_DYN_PATH");
  345.     if (dynpath == 0) {
  346. #if defined(sun4) || defined(sparc)
  347.     sprintf(buf2, ".:%s/dyn.sparc", etdir);
  348. #else
  349.     sprintf(buf2, ".:%s/dyn.68020", etdir);
  350. #endif
  351.     dynpath= buf2;
  352.     }
  353.  
  354.     name2= which(dynpath, buf);
  355.     if (name2 == 0)
  356.     return 0;
  357.  
  358.     if (FindModule(name2))
  359.     return 1;
  360.     
  361.     mp= AddModule(name2, name);
  362.     
  363.     if ((mp->fd= open(name2, O_RDONLY)) < 0)
  364.     return 0;
  365.     
  366.     fprintf(stderr, "\t%s\n", name2);
  367.     
  368.     GetHeader(mp);
  369.     GetSymbols(mp);
  370.  
  371.     close(mp->fd);
  372.     return 1;
  373. }
  374.  
  375. static int try(s)
  376. char *s;
  377. {
  378.     char buf[200], name[100];
  379.     int code= 0, l;
  380.     
  381.     switch (ccversion) {
  382.     case 1:
  383.     if (s[0] == '_' && s[1] == '_') {
  384.         char *st= &s[2];
  385.         s+= 2;
  386.         while (*s++ != '_')
  387.         ;
  388.         if (*s++ == '_') {
  389.         if (s[0] == 'c' && s[1] == 't' && s[2] == 'o' && s[3] == 'r') {
  390.             l= s-2-st;
  391.             strncpy(buf, st, l);
  392.             buf[l]= '\0';
  393.             Testload(buf);
  394.             code= 1;
  395.         }
  396.         }
  397.     }
  398.     break;
  399.     case 2:
  400.     if (strncmp(s, "___ct__", 7) == 0) {
  401.         if (sscanf(&s[7], "%d%s", &l, name) == 2) {
  402.         strncpy(buf, name, l);
  403.         buf[l]= '\0';
  404.         Testload(buf);
  405.         code= 1;
  406.         }
  407.     }
  408.     break;
  409.     case 3:
  410.  
  411. #if 0 /* Naming changed for g++1.37, tom@izf.tno.nl */
  412. /*
  413.    The idea here is that we are given the name of a constructor of
  414.    an object with the same name as the file it is in. For GNU g++
  415.    1.35.1, this will look like "_bar_PSbar...", so we look in
  416.    bar.o.
  417. */
  418.     if (s[0] == '_')
  419.       {  
  420.     char *st1, *st2;
  421.     int l;
  422.  
  423.     s += 1;
  424.     st1 = s;                        /* Start of first part of symbol. */
  425.     while (*s != '_' && *s != '\0')
  426.       s++;
  427.     if (s[0] == '_' && s[1] == 'P' && s[2] == 'S')
  428.       {
  429.         s += 3;
  430.         st2 = s;                    /* Start of second part of symbol. */
  431.         while (*s != '_' && *s != '\0')
  432.           s++;
  433.         l = s-st2;
  434.         if (!strncmp(st1, st2, l))  /* Check they match */
  435.           {
  436.         char buf[200];
  437.         strncpy(buf, st2, l);
  438.         buf[l] = '\0';
  439.         code = Testload(buf);   /* Try to load the file. */
  440.           }
  441.       }
  442.       }
  443. #else
  444.     /* Look for: ___[0-9]+name.*  tom@izf.tno.nl */
  445.  
  446.     if (s[0] == '_' && s[1] == '_' && s[2] == '_')
  447.       {  
  448.     char *st1, *st2;
  449.     int l;
  450.     char num[100], *nump= num;
  451.  
  452.     s += 3;
  453.     st1 = s;                        /* Start of first part of symbol. */
  454.     while (*s != '\0' && isdigit(*s))
  455.       *nump++= *s++;
  456.  
  457.     if (s != st1)
  458.       {
  459.         char buf[1000];
  460.         int len;
  461.  
  462.         *nump= '\0';
  463.         len=atoi(num);
  464.  
  465.         strncpy(buf, s, len);
  466.         buf[len]= '\0';
  467.  
  468.         fprintf(stderr, "Trying: %s\n", buf);
  469.         code= Testload(buf);
  470.       }
  471.       }
  472. #endif
  473.     break;
  474.     }
  475.  
  476.     return code;
  477. }
  478.  
  479. static void Resolve(mp, hashtable)
  480. struct Module *mp;
  481. AssocTable* hashtable;
  482. {
  483.     register struct nlist *symbol, *symp;
  484.     int value;
  485.  
  486.     mp->undefs= 0;
  487.     for (symp= mp->symtab; symp < mp->endp; symp++) {
  488.     if (symp->n_type == N_EXT + N_UNDF) {   /* is not defined here yet. */
  489.         if (symbol= Lookup(hashtable, symp->n_un.n_name)) {
  490.         if (symbol->n_type == N_COMM)
  491.             symp->n_type= N_COMM;
  492.         else
  493.             symp->n_type= N_EXT + N_COMM;
  494.         symp->n_value= symbol->n_value;
  495.         } else {
  496.         if (value= symp->n_value) {    /* is common */
  497.             int rnd= value >= sizeof(double) ? sizeof(double) - 1
  498.                    : value >= sizeof(long) ? sizeof(long) - 1
  499.                    : sizeof(short) - 1;
  500.  
  501.             symp->n_type= N_COMM;
  502.             new_common+= rnd;
  503.             new_common&= ~(long)rnd;
  504.             symp->n_value= new_common;
  505.             new_common+= value;
  506.         } else {  /* is extern */
  507.             fprintf(stderr, "undef %s\n", symp->n_un.n_name);
  508.             mp->undefs++;
  509.         }
  510.         }
  511.     }
  512.     }
  513. }
  514.  
  515. static void UpdateSymtab(mp)
  516. register struct Module *mp;
  517. {
  518.     register struct nlist *symp;
  519.  
  520.     for (symp= mp->symtab; symp < mp->endp; symp++)
  521.     if (symp->n_type == N_TEXT+N_EXT || symp->n_type == N_DATA+N_EXT)
  522.         symp->n_value+= mp->text;
  523. }
  524.  
  525. static int Relocate(mp, common)
  526. register struct Module *mp;
  527. long common;
  528. {
  529.     struct relocation_info *reloc;
  530.     char *address;
  531.     long datum;
  532.     register struct relocation_info *rel, *first_data, *endp;
  533.     struct nlist *symbols= mp->symtab;
  534.  
  535.     reloc= GetRelocInfo(mp);
  536.     if (reloc == 0)
  537.     return 0;
  538.     
  539.     /* text relocation */
  540.     
  541.     first_data= reloc + (mp->header.a_trsize  / sizeof(struct relocation_info));
  542.     endp= reloc + (mp->header.a_trsize+mp->header.a_drsize )/ sizeof(struct relocation_info);
  543.  
  544.     for (rel= reloc; rel < endp; rel++) {
  545.     address= (char*) (rel->r_address + mp->text);
  546.  
  547.     if (rel >= first_data)
  548.         address+= mp->header.a_text;
  549.       
  550. #if defined(sun4) || defined(sparc)
  551.     datum= rel->r_addend;
  552. #else
  553.     switch (rel->r_length) {
  554.     case 0:        /* byte */
  555.         datum= *address;
  556.         break;
  557.     case 1:        /* word */
  558.         datum= *(short*) address;
  559.         break;
  560.     case 2:        /* long */
  561. #ifdef mc68000
  562.         datum= *((long*) address);
  563. #else /* mc680xx */
  564.         *((short*)(&datum))= *((short*)address);
  565.         *((short*)(((char*)(&datum))+2))= *((short*)(address+2));
  566. #endif /* mc68000 */
  567.         break;
  568.     default:
  569.         return bad_format;
  570.     }
  571. #endif
  572.     if (rel->r_extern) {
  573.         struct nlist *symbol= &symbols[rel->r_symbolnum];
  574.         
  575.         switch (symbol->n_type) {
  576.         case N_EXT + N_COMM:    /* old common or external */
  577.         datum+= symbol->n_value;
  578.         break;
  579.         case N_COMM:            /* new common */
  580.         /* datum+= mp->text + mp->header.a_text + mp->header.a_data; */
  581.         datum+= common;
  582.         break;
  583.         default:
  584.         return bad_format;
  585.         }
  586.     } else {                /* is static */
  587.         switch (rel->r_symbolnum & N_TYPE) {
  588.         case N_TEXT:
  589.         case N_DATA:
  590.         datum+= mp->text;
  591.         break;
  592.         case N_BSS:
  593.         datum+= mp->text /* + new_common */;
  594.         break;
  595.         case N_ABS:
  596.         break;
  597.         }
  598.     }
  599. #if defined(sun4) || defined(sparc)
  600.     switch (rel->r_type) {
  601.     case RELOC_DISP8:
  602.     case RELOC_DISP16:
  603.     case RELOC_DISP32:
  604.     case RELOC_WDISP30:
  605.     case RELOC_WDISP22:
  606.         datum-= mp->text;
  607.     }
  608.     switch (rel->r_type) {
  609.     case RELOC_8: case RELOC_DISP8:
  610.         *address= datum;
  611.         break;
  612.     case RELOC_LO10: case RELOC_PC10: case RELOC_BASE10:
  613.         M(address,datum,10);
  614.         break;
  615.     case RELOC_BASE13: case RELOC_13:
  616.         M(address,datum,13);
  617.         break;
  618.     case RELOC_16: case RELOC_DISP16:
  619.         *(short*)address= datum;
  620.         break;
  621.     case RELOC_22:
  622.         M(address,datum,22);
  623.         break;
  624.     case RELOC_HI22: case RELOC_BASE22: case RELOC_PC22:
  625.         M(address, datum >> 10, 22);
  626.         break;
  627.     case RELOC_WDISP22:
  628.         M(address, datum >> 2, 22);
  629.         break;
  630.     case RELOC_JMP_TBL: case RELOC_WDISP30:
  631.         M(address, datum >> 2, 30);
  632.         break;
  633.     case RELOC_32: case RELOC_DISP32:
  634.         *(long*)address= datum;
  635.         break;
  636.     }
  637. #else
  638.     if (rel->r_pcrel)
  639.         datum-= mp->text;
  640.  
  641.     switch (rel->r_length) {
  642.     case 0:      /* byte */
  643.         if (datum < -128 || datum > 127)
  644.         return bad_format;
  645.         *address= datum;
  646.         break;
  647.     case 1:      /* word */
  648.         if (datum < -32768 || datum > 32767) 
  649.         return bad_format;
  650.         *(short*) address= datum;
  651.         break;
  652.     case 2:      /* long */
  653. #ifdef mc68000
  654.         *(long*) address= datum;
  655. #else /* mc680xx */
  656.         *((short*) address)= *((short*) (&datum));
  657.         *((short*)(address+2)= *((short*)(((char*)(&datum))+2)));
  658. #endif /* mc680xx */
  659.         break;
  660.     }
  661. #endif
  662.     }
  663.     
  664.     free(reloc);
  665.  
  666.     return ok;
  667. }
  668.  
  669. int DynLoad(name)
  670. char *name;
  671. {
  672.     char buf[100];
  673.     int allundefs, lastundefs, code= 0;
  674.     struct Module *mp;
  675.     long common= 0;
  676.     struct nlist *symbol, *symp;
  677.     func_ptr ctor;
  678.     
  679.     fprintf(stderr, "loading:\n");
  680.     Testload(name);
  681.     
  682.     lastundefs= 0;
  683.     for (;;) {
  684.     allundefs= 0;
  685.     for (mp= firstModule; mp; mp= mp->next) {
  686.         FindAll(mp, mainhashtable);
  687.         allundefs+= mp->undefs;
  688.     }
  689.     if (allundefs == lastundefs)
  690.         break;
  691.     lastundefs= allundefs;
  692.     }
  693.     
  694.     if (allundefs > 0) {
  695.     int first= 1;
  696.     for (mp= firstModule; mp; mp= mp->next) {
  697.         if (mp->undefs <= 0)
  698.         continue;
  699.         
  700.         for (symp= mp->symtab; symp < mp->endp; symp++)
  701.         if ((symp->n_type & N_EXT)
  702.                 && Lookup(mainhashtable, symp->n_un.n_name) == 0) {
  703.             if (first) {
  704.             fprintf(stderr, "undefined symbols:\n");
  705.             first= 0;
  706.             }
  707.             fprintf(stderr, "\t%s\n", symp->n_un.n_name);
  708.         }
  709.     }
  710.     _exit(1);
  711.     }
  712.     
  713.     if (new_common > 0)
  714.     common= (long) calloc(1, new_common);
  715.     new_common= 0;
  716.     
  717.     for (mp= firstModule; mp; mp= mp->next) {
  718.     if ((mp->fd= open(mp->name, O_RDONLY)) < 0)
  719.         perror("open");
  720.         
  721.     Resolve(mp, mainhashtable);
  722.     allundefs+= mp->undefs;
  723.     lastundefs= allundefs;
  724.     GetTextAndData(mp);
  725.     Relocate(mp, common);
  726.     UpdateSymtab(mp);
  727.     close(mp->fd);
  728.     }
  729.     
  730.     fprintf(stderr, "static ctors:\n");
  731.     for (mp= firstModule; mp; mp= mp->next) {
  732.     for (symp= mp->symtab; symp < mp->endp; symp++) {
  733.         if ((symp->n_type & N_EXT) && symp->n_un.n_name[1] == '_') {
  734.         if (strncmp(symp->n_un.n_name, STI, STIlen) == 0) {
  735.             if (symbol= Lookup(mainhashtable, symp->n_un.n_name)) {
  736.             ctor= (func_ptr) symbol->n_value;
  737.             if (ctor) {
  738.                 fprintf(stderr, "\t%s\n", symp->n_un.n_name);
  739.                 (*ctor)();            /* call static constructors */
  740.             }
  741.             }
  742.         } else if (strncmp(symp->n_un.n_name, STD, STDlen) == 0) {
  743.             if (symbol= Lookup(mainhashtable, symp->n_un.n_name))
  744.             mp->dtor= (func_ptr) symbol->n_value;
  745.         }
  746.         }
  747.     }
  748.     }
  749.     firstModule= 0;
  750.     return code;  
  751. }
  752.  
  753. static struct nlist *Copy(sym)
  754. struct nlist *sym;
  755. {
  756.     struct nlist *tmp;
  757.     
  758.     tmp= (struct nlist*) calloc(1, sizeof(struct nlist));
  759.     *tmp= *sym;
  760.     tmp->n_un.n_name= strsave(sym->n_un.n_name);
  761.     return tmp;
  762. }
  763.  
  764. void *dynlinkinit(me, ccvers, etd)
  765. char *me, *etd;
  766. int ccvers;
  767. {
  768.     register struct nlist *symp;
  769.     char *name;
  770.     
  771.     if (mainhashtable)
  772.     return;
  773.     
  774.     ccversion= ccvers;
  775.     switch (ccversion) {
  776.     case 1:     /* cfront 1.2 */
  777.     STI= "__STI";
  778.     STD= "__STD";
  779.     break;
  780.     case 2:     /* cfront 2.0 */
  781.     STI= "___sti";
  782.     STD= "___std";
  783.     break;
  784.     case 3:     /* G++ */
  785.     STI= "__GLOBAL_$I$";
  786.     STD= "__GLOBAL_$D$";
  787.     break;
  788.     }
  789.     STIlen= strlen(STI);
  790.     STDlen= strlen(STD);
  791.     etdir= etd;
  792.     name= which(getenv("PATH"), me);
  793.     mainmodule.fd= open(name, O_RDONLY);
  794.     GetHeader(&mainmodule);
  795.     GetSymbols(&mainmodule);
  796.     close(mainmodule.fd);
  797.     
  798.     mainhashtable= NewAssocTable();
  799.     
  800.     for (symp= mainmodule.symtab; symp < mainmodule.endp; symp++)
  801.     if ((symp->n_type & N_EXT) && strcmp(symp->n_un.n_name, "_main"))
  802.         Assoc(mainhashtable, Copy(symp));
  803.     free(mainmodule.symtab);
  804. }
  805.  
  806. char *DynLookup(name)
  807. char *name;
  808. {
  809.     struct nlist *symbol;
  810.     
  811.     if (symbol= Lookup(mainhashtable, name))
  812.     return (char*) symbol->n_value;
  813.     return 0;
  814. }
  815.  
  816. static void CallDtors(mp)
  817. struct Module *mp;
  818. {
  819.     if (mp) {
  820.     CallDtors(mp->next);
  821.     if (mp->dtor) {
  822.         fprintf(stderr, "dtor of %s\n", mp->name1);
  823.         (*mp->dtor)();            /* call static destructors */
  824.     }
  825.     }
  826. }
  827.  
  828. void DynCleanup()
  829. {
  830.     if (firstModule) {
  831.     CallDtors(firstModule);
  832.     firstModule= 0;
  833.     }
  834. }
  835.  
  836. func_ptr DynCall(name)
  837. char *name;
  838. {
  839.     char buf[100];
  840.     struct nlist *symbol;
  841.     
  842.     sprintf(buf, "_%s", name);
  843.     if (symbol= Lookup(mainhashtable, buf))
  844.     return (func_ptr) symbol->n_value;
  845.     return func_error;
  846. }
  847.  
  848. #else sun
  849.  
  850. void *dynlinkinit(me, ccversion, etdir)
  851. char *me, *etdir;
  852. int ccversion;
  853. {
  854.     return 0;
  855. }
  856.  
  857. char *DynLookup(name)
  858. char *name;
  859. {
  860.     return 0;
  861. }
  862.  
  863. func_ptr DynCall(name)
  864. char *name;
  865. {
  866.     return func_error;
  867. }
  868.  
  869. int DynLoad(name)
  870. char *name;
  871. {
  872.     return 0;
  873. }
  874.  
  875. #endif /* sun */
  876.